package com.lfz.demo.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lfz.demo.entity.Menu;
import com.lfz.demo.entity.Role;
import com.lfz.demo.service.MenuService;
import com.lfz.demo.service.RoleService;
import com.lfz.demo.utils.RedisUtil;
import com.lfz.demo.utils.TreeNode;
import com.lfz.demo.vo.DataView;
import com.lfz.demo.vo.RoleVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author lfz
 * @date 2025/3/4 10:26
 */
@RestController
@RequestMapping("/role")
public class RoleController {

    private static final Logger logger = LoggerFactory.getLogger(MenuController.class);
    // 缓存时间常量（单位：分钟）
    private static final int CACHE_EXPIRE = 1440; //缓存过期时间（1440分钟）。
    private static final String CACHE_PREFIX = "roleMenu:"; //缓存键前缀，避免键冲突。

    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 查询所有角色（分页），带有查询条件
     */
    @GetMapping("/loadAllRole")
    public DataView loadAllRole(RoleVo roleVo){
        // 1、生成缓存键
        String cacheKey = CACHE_PREFIX + "loadAllRole_p" + roleVo.getPage();

        try {
            // 2、尝试使用redis缓存获取数据
            DataView cacheData = (DataView) redisUtil.get(cacheKey);
            // 2.1、判断cacheData是否为空，不为空则直接返回redis缓存的数据
            if (cacheData != null){
                return cacheData;
            }
        } catch (Exception e){
            // 处理异常
            e.printStackTrace();
            // 控制台日志提示
            logger.error("Redis连接失败，降级查询Mysql");
        }

        try {
            // Mysql查询逻辑（Mybatis-plus）
            // 查询所有带有模糊查询条件 带有分页
            IPage<Role> page = new Page<>(roleVo.getPage(),roleVo.getLimit());
            QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
            // 模糊查询
            queryWrapper.like(StringUtils.isNoneBlank(roleVo.getName()),"name",roleVo.getName());
            queryWrapper.like(StringUtils.isNoneBlank(roleVo.getRemark()),"remark",roleVo.getRemark());
            roleService.page(page,queryWrapper);

            // 设置redis缓存
            redisUtil.set(cacheKey, new DataView(page.getTotal(), page.getRecords()), CACHE_EXPIRE);
            return new DataView(page.getTotal(), page.getRecords());
        } catch (Exception e){
            e.printStackTrace();
            logger.error("权限菜单查询失败");
            // 处理空指针事件
            return new DataView(0L, Collections.emptyList());
        }
    }

    /**
     * 添加角色
     */
    @PostMapping("/addRole")
    public DataView addRole(Role role){
        DataView dataView = new DataView();
        boolean save = roleService.save(role);
        if (!save){
            dataView.setCode(100);
            dataView.setMsg("发生错误，添加角色失败！");
        }
        // 清理相关缓存
        clearRelatedCaches();
        dataView.setCode(200);
        dataView.setMsg("添加角色成功！");
        return dataView;
    }

    /**
     * 编辑、修改角色
     */
    @PostMapping("/updateRole")
    public DataView updateRole(Role role){
        DataView dataView = new DataView();
        boolean b = roleService.updateById(role);
        if (!b){
            dataView.setCode(100);
            dataView.setMsg("发生错误，修改角色失败！");
        }
        // 清理权限相关redis缓存
        clearRelatedCaches();
        dataView.setCode(200);
        dataView.setMsg("修改角色成功！");
        return dataView;
    }

    /**
     * 删除角色
     */
    @PostMapping("/deleteRole")
    public DataView deleteRole(Role role){
        DataView dataView = new DataView();
        boolean b = roleService.removeById(role);
        if (!b){
            dataView.setCode(100);
            dataView.setMsg("发生错误，删除角色失败！");
        }
        // 清理权限相关redis缓存
        clearRelatedCaches();
        dataView.setCode(200);
        dataView.setMsg("删除角色成功！");
        return dataView;
    }

    /**
     * 初始化下拉列表所具有的权限
     * 根据角色查询菜单
     * select mid from role_menu where rid = ?
     */
    @RequestMapping("/initPermissionByRoleId")
    public DataView initPermissionByRoleId(Integer roleId){
        // 生成缓存键
        String cacheKey = CACHE_PREFIX + "initPermissionByRoleId_id=" + roleId;

        try {
            // 尝试从redis缓存获取数据
            DataView cacheData = (DataView) redisUtil.get(cacheKey);
            // 判断cacheData是否为空，不为空则直接返回redis缓存数据
            if (cacheData != null){
                return cacheData;
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error("Redis连接失败，降级查询Mysql");
        }

        try {
            // 1、创建条件构造器
            QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
            // 2、把所有的菜单权限查出来
            List<Menu> allPermissions = menuService.list();
            // 3、根据角色rid【roleId】查询所有菜单的mid
            List<Integer> currentRolePermissions = roleService.queryAllPermissionsByRid(roleId);
            // 4、rid mid 所有的id，去查询菜单和角色的数据
            List<Menu> menus = null;
            // 5、查询到 mid rid
            if (currentRolePermissions.size() > 0) {
                queryWrapper.in("id", currentRolePermissions);
                menus = menuService.list(queryWrapper);
            } else {
                menus = new ArrayList<>();
            }
            // 6、返回前台的格式，带有层级关系 TREENODE
            List<TreeNode> nodes = new ArrayList<>();
            for (Menu allpermission : allPermissions){
                String checkArr = "0";
                for (Menu currentPermission : menus){
                    if (allpermission.getId().equals(currentPermission.getId())){
                        checkArr = "1";
                        break;
                    }
                }
                Boolean spread = (allpermission.getOpen()==null || allpermission.getOpen() == 1)? true:false;
                nodes.add(new TreeNode(allpermission.getId(),allpermission.getPid(),allpermission.getTitle(),spread,checkArr));
            }

            //设置redis缓存
            redisUtil.set(cacheKey, new DataView(nodes), CACHE_EXPIRE);
            return new DataView(nodes);
        }catch (Exception e){
            e.printStackTrace();
            logger.error("查询权限下拉列表异常");
            return new DataView(0L, Collections.emptyList());
        }
    }

    /**
     * 点击确认分配权限的时候
     * 插入数据库表【role_menu】
     *
     * var params = "rid="+data.id;
     * console.log(params);
     * $.each(permissionData,function (index, item) {
     *     params+="&mids="+item.nodeId;
     * });
     *
     */
    @RequestMapping("/saveRolePermission")
    public DataView saveRolePermission(Integer rid, Integer[] mids){
        // 1、根据rid删除之前的mid权限
        roleService.deleteRoleByRid(rid);
        // 2、保存权限
        if (mids != null && mids.length > 0){
            for (Integer mid : mids){
                roleService.saveRoleMenu(rid, mid);
            }
        }
        DataView dataView = new DataView();
        // 清理权限相关redis缓存
        clearRelatedCaches();
        dataView.setCode(200);
        dataView.setMsg("菜单权限分配成功！");
        return dataView;
    }

    /**
     * 清理相关缓存
     */
    private void clearRelatedCaches(){
        try {
            redisUtil.deletePattern(CACHE_PREFIX + "*");
            logger.info("成功清理权限相关缓存");
        }catch (Exception e){
            e.printStackTrace();
            logger.error("缓存清理失败", e);
        }
    }
}
